/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.com.claro.administracionSolicitudes.seguridad;

import co.com.claro.administracionSolicitudes.dao.GrupoJpaController;
import co.com.claro.administracionSolicitudes.dao.UsuarioJpaController;
import co.com.claro.administracionSolicitudes.dao.exceptions.ClaroException;
import co.com.claro.administracionSolicitudes.entity.Grupo;
import co.com.claro.administracionSolicitudes.entity.Usuario;
import co.com.claro.administracionSolicitudes.entity.enums.EstadoActividadEnum;
import co.com.claro.administracionSolicitudes.entity.enums.TipoEmpleadoEnum;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;

/**
 *
 * @author Mike
 */
@Stateless
public class EJBSeguridad implements EJBSeguridadLocal {

    @Inject
    private UsuarioJpaController usuarioJpa;

    @Inject
    private GrupoJpaController grupoJpa;

    @Override
    public Usuario findUsuarioActivoPorUsernameExacto(String username) {
        return usuarioJpa.findUsuarioByUsernameExacto(username, EstadoActividadEnum.ACTIVO.getId(), EstadoActividadEnum.ACTIVO.getId());
    }

    @Override
    public List<Grupo> findGruposSinUsuarios(EstadoActividadEnum estado) {
        return grupoJpa.findGrupoSinUsuarios(estado.getId());
    }

    /**
     * Método que genera el username del usuario dependiendo si el usuario es
     * externo ó temporal según las reglas del cliente:
     *
     * - Si el usuario es externo, se debe colocar el prefijo 'ext', la primer
     * letra del nombre y las 3 primeras letras del apellido.
     *
     * - Si el usuario es temporal, se debe colocar la primer letra del nombre,
     * las 3 primeras letras del apellido y los 2 últimos números de la cedula.
     *
     * @param usuario, el usuario al que se le va a generar el username
     */
    @Override
    public void generarUsername(Usuario usuario) {
        if (TipoEmpleadoEnum.EXTERNO.getId() == usuario.getTipoEmpleado().getIdTipoEmpleado()) {
            generarUsernameExterno(usuario);
        } else if (TipoEmpleadoEnum.TEMPORAL.getId() == usuario.getTipoEmpleado().getIdTipoEmpleado()) {
            generarUsernameTemporal(usuario);
        }
    }

    /**
     * Método que genera un username para un usuario externo
     *
     * @param usuario, el usuario al que se le va a generar el username
     */
    private void generarUsernameExterno(Usuario usuario) {
        final String externo = "ext";
        char[] nombreArray = usuario.getNombres().toLowerCase().split("\\s")[0].toCharArray();
        String[] apellidos = usuario.getApellidos().toLowerCase().split("\\s");
        String apellido = apellidos[0].substring(0, 3);
        StringBuilder username = new StringBuilder(externo);

        username.append(nombreArray[0]);
        username.append(apellido);

        //Si retorna algún valor quiere decir que el username ya está asignado y se debe cambiar
        if (findUsuarioActivoPorUsernameExacto(username.toString()) != null) {
            //En caso de que el username ya exista en la base de datos se tomará las 3 primeras letras
            //del segundo apellido
            apellido = apellidos[1].substring(0, 3);

            username.delete(0, username.length());
            username.append(externo);
            username.append(nombreArray[0]);
            username.append(apellido);
        }

        usuario.setUsername(username.toString());
    }

    /**
     * Método que genera un username para un usuario temporal
     *
     * @param usuario, el usuario al que se le va a generar el username
     */
    private void generarUsernameTemporal(Usuario usuario) {
        char[] nombreArray = usuario.getNombres().toLowerCase().split("\\s")[0].toCharArray();
        String apellido = usuario.getApellidos().toLowerCase().split("\\s")[0].substring(0, 3);
        String cedula = Long.toString(usuario.getNumeroDocumento());
        String numerosCedula = cedula.substring((cedula.length() - 3), (cedula.length() - 1));
        StringBuilder username = new StringBuilder();

        username.append(nombreArray[0]);
        username.append(apellido);
        username.append(numerosCedula);

        //Si retorna algún valor quiere decir que el username ya está asignado y se debe cambiar
        if (findUsuarioActivoPorUsernameExacto(username.toString()) != null) {
            //TODO: gernerar el algoritmo para que varie el username a crear
        }

        usuario.setUsername(username.toString());
    }

    /**
     * Método que toma una cadena de caracteres y la pasa por el algoritmo de
     * encripción MD5 y retorna la cadena de caracteres encriptada como una
     * cadena de caracteres alfanumericos del tipo Hexadecimal.
     *
     * @param password, contraseña a ser encriptada.
     * @return String, Cadena de caracteres encriptada en formato hexadecimal.
     * @throws ClaroException, si no puede encriptar la cadena de caracteres.
     */
    @Override
    public String encriptarPassword(String password) throws ClaroException {
        MessageDigest md;
        byte byteData[];
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(password.getBytes());
            byteData = md.digest();

            //Se convierte el arreglo de bytes a una cadena de hexadecimales
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }

            return sb.toString();
        } catch (NoSuchAlgorithmException ex) {
            throw new ClaroException("Error encriptando el password. | EJBSeguridad | encriptarPassword", ex);
        }
    }
}
